<template>
  <el-upload
    v-bind="upload"
    ref="uploadRef"
    :http-request="handleUpload">
    <slot></slot>
  </el-upload>
</template>

<script lang="ts" setup>
import { computed, ref } from "vue";
import { getToken } from "@/utils/common";
import {
  ElMessage,
  UploadFile,
  UploadFiles,
  UploadRequestOptions,
} from "element-plus";
import { getUploadInfo } from "@/app/api/upload";
import COS from "cos-js-sdk-v5";
import OSS from "ali-oss";

const prop = defineProps({
  type: {
    type: String,
    default: "image",
  },
});

const emits = defineEmits(["success"]);

const uploadRef = ref<Record<string, any> | null>(null);

// 获取上传凭证
const getUploadCredentials = async () => {
  try {
    const res = await getUploadInfo();
    if (res.code === 1) {
      return res.data;
    } else {
      console.error(res.msg);
      throw new Error(res.msg || "获取上传凭证失败");
    }
  } catch (e) {
    console.error(e);
    throw new Error(JSON.stringify(e) || "获取上传凭证失败");
  }
};

// 自定义上传方法
const handleUpload = async (options: UploadRequestOptions) => {
  const { file } = options;

  try {
    // 1. 获取上传凭证
    const credentials = await getUploadCredentials();
    const { cloud, bucket, region, domain } = credentials;

    // 2. 生成唯一文件名
    const extension = file.name.split(".").pop();
    const fileName = `${Date.now()}-${Math.random()
      .toString(36)
      .substring(2, 10)}.${extension}`;

    let fileUrl = "";

    // 3. 根据云服务类型选择不同上传方式
    if (cloud === "tencent") {
      // 腾讯云COS上传
      const cos = new COS({
        SecretId: credentials.tmpSecretId,
        SecretKey: credentials.tmpSecretKey,
        SecurityToken: credentials.sessionToken,
      });

      await new Promise((resolve, reject) => {
        cos.uploadFile(
          {
            Bucket: bucket,
            Region: region,
            Key: fileName,
            Body: file,
            SliceSize: 1024 * 1024 * 800,
          },
          (err, data) => {
            if (err) reject(err);
            else {
              // 使用自定义域名或默认域名
              fileUrl = domain
                ? `${domain}/${fileName}`
                : `https://${bucket}.cos.${region}.myqcloud.com/${fileName}`;
              console.log("fileUrl", fileUrl);
              resolve(fileUrl);
            }
          }
        );
      });
    } else if (cloud === "aliyun") {
      // 阿里云OSS上传
      const client = new OSS({
        bucket,
        region,
        accessKeyId: credentials.accessKeyId,
        accessKeySecret: credentials.accessKeySecret,
        stsToken: credentials.securityToken,
        secure: true, // 使用HTTPS
      });

      const result = await client.put(fileName, file, {});

      fileUrl = domain
        ? `${domain}/${fileName}`
        : result.url.replace(/^http:/, "https:"); // 强制使用HTTPS
      console.log("fileUrl", fileUrl);
    } else {
      console.error("不支持的云存储服务");
      throw new Error("不支持的云存储服务");
    }

    // 4. 手动触发成功回调（让el-upload更新状态）
    options.onSuccess({ code: 1, data: fileUrl });
  } catch (error: any) {
    options.onError(error);
  }
};

// 计算属性配置
const upload = computed(() => ({
  action: "#",
  multiple: true,
  accept: prop.type == "image" ? ".bmp,.png,.jpeg,.jpg,.gif" : ".mp4,.mov,.avi",
  showFileList: true,
  beforeUpload: (file: File) => {
    // 文件大小限制（如：图片50M，视频800M）
    const isImage = prop.type === "image";
    const maxSize = isImage ? 50 * 1024 * 1024 : 800 * 1024 * 1024;

    if (file.size > maxSize) {
      ElMessage.error(
        `${isImage ? "图片" : "视频"}大小不能超过${isImage ? "50MB" : "800MB"}`
      );
      return false;
    }
    return true;
  },
  onSuccess: (
    response: any,
    uploadFile: UploadFile,
    uploadFiles: UploadFiles
  ) => {
    if (response.code >= 1) {
      emits("success", response.data);
      uploadRef.value?.handleRemove(uploadFile);
    } else {
      uploadFile.status = "fail";
      uploadRef.value?.handleRemove(uploadFile);
      ElMessage({ message: response.msg, type: "error" });
    }
  },
  onError: (error: any) => {
    console.error("上传失败:", error);
    ElMessage({
      message: `上传失败: ${error.message || "未知错误"}`,
      type: "error",
    });
  },
}));
</script>
